import java.applet.Applet;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;

import javax.imageio.ImageIO;


public class KombatApplet extends Applet implements KeyListener, Runnable   {
	
	private Player p1;
	private Player p2;
	private ArrayList<BufferedImage> spritesP1R;
	private ArrayList<BufferedImage> spritesP1L;
	private ArrayList<BufferedImage> spritesP2R;
	private ArrayList<BufferedImage> spritesP2L;

	private int width = 400; // default == 400
	private int height = 250; // default == 250
	
	//private int spriteP1 = 1;
	
	private int countFPS; // Counting FPS (60fps/sec) for timing. Increases by 1 every 1000/60 milliseconds.
	private int countSec;
	private boolean second;
	
	private boolean isPackOnScreen;
	// where the pack is on the screen
	private int packLocation;
	// how many points the pack is worth
	private int packValue;
	
	Thread runner;
	//String message = "Fatal Fighters!!!";
	String message;
	BufferedImage imageA; //Place holder image for now
	
	private Image backbuffer;
	private Graphics backg;
	
	
	public void init() { 
		setSize(width, height);
		message = "Fatal Fighting!!! Alpha ver. 0.001412";
		
		try {
			imageA = ImageIO.read(new File("UrbanCity-Flatten.png"));
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		try {
			p1 = new RedPlayer(60, height - 160, true, 10, 15, 5, 9, 12, 16);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		spritesP1R = p1.getSpritesR();
		spritesP1L = p1.getSpritesL();
		
		try {
			p2 = new BluePlayer(width - 200, height - 140, false, 13, 18, 4, 8, 10, 16);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		spritesP2R = p2.getSpritesR();
		spritesP2L = p2.getSpritesL();
		
		backbuffer = createImage(width, height);
		backg = backbuffer.getGraphics();
		
		// Animation starts here.
		runner = new Thread(this);
		runner.start();
		
		// Added actions goes under here.
		addKeyListener(this);
	}
	
	public void paint(Graphics g){
		update(g);
	}
	
	public void update(Graphics g){
		drawBuffer();
		g.drawImage(backbuffer, 0,0, this);
		try
		{
		Thread.sleep(10);
		}
		catch(InterruptedException e)
		{}
		//call repaint
	}
	
	public void drawBuffer() {
		backg.drawImage(imageA, 0 - width/2, 0 - height - 90, null);
		//g.drawLine(0, height - 30, width, height - 30); base line
		
		//backg.setColor(p1.getColor());
		//g.fillOval(p1.getPoint().getX(), p1.getPoint().getY(), 20, 20);
		if(p1.isFacing(p2))
			backg.drawImage(spritesP1R.get(p1.getSprite()), p1.getPoint().getX(),  p1.getPoint().getY(), null);
		else if(!p1.isFacing(p2))
			backg.drawImage(spritesP1L.get(p1.getSprite()), p1.getPoint().getX(),  p1.getPoint().getY(), null);
		
		/*	lifeBar(p1, backg);
		energyBar(p1, backg);*/
		
		//backg.setColor(p2.getColor());
		if(p2.isFacing(p1))
			backg.drawImage(spritesP2R.get(p2.getSprite()), p2.getPoint().getX(),  p2.getPoint().getY(), null);
		else if(!p2.isFacing(p1))
			backg.drawImage(spritesP2L.get(p2.getSprite()), p2.getPoint().getX(),  p2.getPoint().getY(), null);
		lifeBar();
		energyBar();
		
		showStatus(message);
		
		// draws a health pack
		
		//drawHealthPack(); //Screw the health pack! >:(
		
		// Displays message when player(s) are dead
		backg.setColor(Color.WHITE);
		if(p1.isDead() && p2.isDead()){
			backg.drawString("What is this!? Both Players have lost!!!", width/2 - 50, (int)(height/3));
		} else if(p1.isDead()){
			backg.drawString("Player 1 lose!", width/2, (int)(height/3));
		} else if(p2.isDead()){
			backg.drawString("Player 2 lose!", width/2, (int)(height/3));
		}
	}
	
	public void run() {
		while(true) {
			repaint();
			//message = countSec + ": " + countFPS;
			
			// Animating
			animationMain(p1);
			animationMain(p2);
			
			// Moving
			if(p1.isWalking() && p1.isIdle()){
				try {
					moveP(p1, p1.getSide());
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			if(p2.isWalking() && p2.isIdle()){
				try {
					moveP(p2, p2.getSide());
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			
			if(p1.isJumping() && p1.isIdle()){
				jumpP(p1);
			}
			if(p2.isJumping() && p2.isIdle()){
				jumpP(p2);
			}

			
			// Jumping
			//jump();
			
			/*if(p1.isJumping()){
				jumpP(p1);
			}
			if(p2.isJumping()){
				jumpP(p2);
			}*/
			
			// Regaining Energy
			energyRegain();
			
			// Pack Stuff
			//HealthPack();
			
			//System.out.println(p1.getAlert());
			try {
				Thread.sleep(1000 / 60); 
				countFPS++;
				if(countFPS % 60 == 0){
					second = true;
					countSec++;
				}

			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
	
	// Health Pack (cancled for now)
	public void drawHealthPack(){
		if(!isPackOnScreen && (countFPS % 1000 == 0)) {
			int location = (int)(Math.random() * width);
			int value = (int)(Math.random() * 10) + 10;
			
			packLocation = location;
			packValue = value;
			
			//nearPack.clear();
			
			// ArrayList of healthpack nearby location;
			
			// Creates a health pack
			backg.setColor(Color.CYAN);
			backg.fillRect(location, height - 100, 15, 15);
			isPackOnScreen = true;
		} else {
			backg.setColor(Color.CYAN);
			backg.fillRect(packLocation, height - 100, 15, 15);
		}
	}
	
	public void HealthPack(){
		int temp = packLocation - 5;
		ArrayList<Integer> lol = new ArrayList<Integer>();
		
		for(int i = 1; i <= 10; i++) {
			lol.add(temp);
			temp++;
		}
		if(contains(p1.getPoint().getX(), lol)) {
			System.out.println("Health pack!");
			if(p1.getLifePoints() + packValue > p1.getMaxLimitLP()) {
				p1.setLifePoints(p1.getMaxLimitLP());
			} else {
				p1.setLifePoints(p1.getLifePoints() + packValue);
			}
			isPackOnScreen = false;	
		}
		if(contains(p2.getPoint().getX(), lol)) {
			System.out.println("Health pack!");
			if(p2.getLifePoints() + packValue > p2.getMaxLimitLP()) {
				p2.setLifePoints(p2.getMaxLimitLP());
			} else {
				p2.setLifePoints(p2.getLifePoints() + packValue);
			}
			isPackOnScreen = false;
		}

	}
		
	public boolean contains(int numba, ArrayList<Integer> lon) {
		int count = 0;
		for(int i = 0; i < lon.size(); i++) {
			if(lon.get(i) == numba) {
				count++;
			}
		}
		return count == 1;
	}

	// Battle Scene props goes under here.
	
	public void lifeBar(){
		backg.setColor(p1.getColor());
		backg.fillRect(0, 0, (int)(p1.getLifePoints() * 1.5), 25);
		
		backg.setColor(p2.getColor());
		backg.fillRect(width - (int)(p2.getLifePoints() * 1.5), 0, (int)(p2.getLifePoints() * 1.5), 25);
	}
	
	public void energyBar(){
		backg.setColor(p1.getColor());
		backg.fillRect(0, 35, (int)p1.getEnergyPoints(), 10);
		
		backg.setColor(p2.getColor());
		backg.fillRect(width - (int)p2.getEnergyPoints(), 35, (int)p2.getEnergyPoints(), 10);
	}

	public void energyRegain(){
		if((countSec % 1) == 0 && second) {
			if(p1.getEnergyPoints() < p1.getMaxLimitEP() && (!p1.isBlocking())) {
				p1.setEnergyPoints(p1.getEnergyPoints() + 2);
				second = false;
			}
			if(p2.getEnergyPoints() < p2.getMaxLimitEP() && (!p2.isBlocking())) {
				p2.setEnergyPoints(p2.getEnergyPoints() + 2);
				second = false;
			}
		}
	}
	
	// Animation related stuff goes under here.
	public void animationMain(Player p){
		p.setCountFrame(p.getCountFrame() + 1);
		
		if(p.getAniState() == 0){
			animationAlert(p);
		}
		if(p.getAniState() == 1 && p.getAniState() != 2){
			animationWalk(p);
		}
		if(p.getAniState() == 2){
			animationJump(p);
		}
		if(p.getAniState() == 3){
			animationBlock(p);
		}
		if(p.getAniState() == 4){
			animationPunch(p);
		}
		if(p.getAniState() == 5){
			animationKick(p);
		}
	}
	
	public void animationAlert(Player p){
		//System.out.println(p.getCountFrame());
		if((p.getTeam() && p.getCountFrame() % 10 == 0) ||
			(!p.getTeam() && p.getCountFrame() % 20 == 0)){
			p.setCountFrame(0);
			if(p.getCountAni() < p.getAlert()){
				p.setCountAni(p.getCountAni() + 1);
				p.setSprite(p.getCountAni());
				//System.out.println(p.getSprite());
			} else{
				//System.out.println("reset");
				p.setCountAni(0);
				p.setSprite(p.getCountAni());
				//System.out.println(p.getSprite());
			} 
		}	
	}
	
	public void animationWalk(Player p){
		if(p.getCountFrame() % 10 == 0){
			p.setCountFrame(0);
			if(p.getCountAni() < p.getWalk()){
				p.setCountAni(p.getCountAni() + 1);
				p.setSprite(p.getCountAni());
				//System.out.println(p.getSprite());
			} else{
				//System.out.println("reset");
				p.setCountAni(p.getAlert() + 1);
				p.setSprite(p.getCountAni());
				//System.out.println(p.getSprite());
			} 
		}	
	}
	
	public void animationJump(Player p){
		if(p.getCountFrame() % 2 == 0){
			p.setCountFrame(0);
			if(p.getCountAni() < p.getJump()){
				p.setCountAni(p.getCountAni() + 1);
				p.setSprite(p.getCountAni());
				//System.out.println(p.getSprite());
			} else{
				//System.out.println("reset");
				p.setCountAni(p.getWalk() + 2);
				p.setSprite(p.getCountAni());
			}
		}
	}

	public void animationBlock(Player p){
		p.setSprite(p.getBlock());
	}
	
	public void animationPunch(Player p){
		if(p.getCountFrame() % 5 == 0){
			p.setCountFrame(0);
			if(p.getCountAni() < p.getPunchNum()){
				p.setCountAni(p.getCountAni() + 1);
				p.setSprite(p.getCountAni());
				//System.out.println(p.getSprite());
			} else if(p.getCountAni() >= p.getPunchNum()){
				//System.out.println("reset");
				p.setAniState(0);
				p.setIdle(true);
				//System.out.println(p.getSprite());
			} 
			// Player 1
			if(p.getTeam() && p.getCountAni() == 32){
				p.punch(p2, 60, 5, 4);
			}
			// Player 2
			if(!p.getTeam() && p.getCountAni() == 12){
				p.punch(p1, 45, 4, 3);
			}
			if(!p.getTeam() && p.getCountAni() == 16){
				p.punch(p1, 40, 3, 2);
			}
		}
	}
	
	public void animationKick(Player p){
		if(p.getCountFrame() % 4 == 0){
			p.setCountFrame(0);
			if(p.getCountAni() < p.getKickNum()){
				p.setCountAni(p.getCountAni() + 1);
				p.setSprite(p.getCountAni());
				//System.out.println(p.getSprite());
			} else if(p.getCountAni() >= p.getKickNum()){
				//System.out.println("reset");
				p.setAniState(0);
				p.setIdle(true);
				//System.out.println(p.getSprite());
			} 
			// Player 1
			if(p.getTeam() && p.getCountAni() == 43){
				p.kick(p2, 70, 11, 10);
			}
			
			// Player 2
			if(!p.getTeam() && p.getCountAni() == 23){
				p.kick(p1, 60, 9, 7);
			}
		}	
	}
	
	// Moving player stuff goes under here.
	
	public void moveP(Player player, int keyCode) throws InterruptedException {
		// Moving left
		if(keyCode == KeyEvent.VK_LEFT && !(player.isJumping()) && player.getPoint().getX() - 2 > 10|| 
				keyCode == KeyEvent.VK_A && !(player.isJumping()) && player.getPoint().getX() - 2 > 10){
			player.setPoint(new Point(player.getPoint().getX() - 2, player.getPoint().getY()));
		}
		// Moving left while jumping (slower)
		else if(keyCode == KeyEvent.VK_LEFT && player.isJumping() && player.getPoint().getX() - 1 > 10|| 
					keyCode == KeyEvent.VK_A && player.isJumping() && player.getPoint().getX() - 1 > 10){
			player.setPoint(new Point(player.getPoint().getX() - 1, player.getPoint().getY()));
		} 
		// Moving right
		else if(keyCode == KeyEvent.VK_RIGHT && !(player.isJumping()) && player.getPoint().getX() + 2 < width - 70 || 
					keyCode == KeyEvent.VK_D && !(player.isJumping()) && player.getPoint().getX() + 2 < width - 70 ){
			player.setPoint(new Point(player.getPoint().getX() + 2, player.getPoint().getY()));
		}
		// Moving right while jumping (slower)
		else if(keyCode == KeyEvent.VK_RIGHT && player.isJumping() && player.getPoint().getX() + 1 < width - 70 || 
				keyCode == KeyEvent.VK_D && player.isJumping() && player.getPoint().getX() + 1 < width - 70 ){
		player.setPoint(new Point(player.getPoint().getX() + 1, player.getPoint().getY()));
		}
	}
	
	public void jumpP(Player p){
		if(p.getJumpCount() == 0){
			p.setPoint(new Point(p.getPoint().getX(), p.getPoint().getY() - 25));
			p.setJumpCount(p.getJumpCount() + 1);
		} else if(p.getJumpCount() == 1){
			p.setPoint(new Point(p.getPoint().getX(), p.getPoint().getY() - 15));
			p.setJumpCount(p.getJumpCount() + 1);
		} else if(p.getJumpCount() == 2){
			p.setPoint(new Point(p.getPoint().getX(), p.getPoint().getY() - 10));
			p.setJumpCount(p.getJumpCount() + 1);
		} else if(p.getJumpCount() == 3){
			p.setPoint(new Point(p.getPoint().getX(), p.getPoint().getY() - 7));
			p.setJumpCount(p.getJumpCount() + 1);
		} else if(p.getJumpCount() == 4){
			p.setPoint(new Point(p.getPoint().getX(), p.getPoint().getY() - 4));
			p.setJumpCount(p.getJumpCount() + 1);
		} else if(p.getJumpCount() == 5){
			p.setPoint(new Point(p.getPoint().getX(), p.getPoint().getY() - 2));
			p.setJumpCount(p.getJumpCount() + 1);
		} else if(p.getJumpCount() == 6){
			p.setPoint(new Point(p.getPoint().getX(), p.getPoint().getY() - 1));
			p.setJumpCount(p.getJumpCount() + 1);
		} else if(p.getJumpCount() == 7){
			p.setPoint(new Point(p.getPoint().getX(), p.getPoint().getY()));
			p.setJumpCount(p.getJumpCount() + 1);
		} else if(p.getJumpCount() == 8){
			p.setPoint(new Point(p.getPoint().getX(), p.getPoint().getY() + 1));
			p.setJumpCount(p.getJumpCount() + 1);
		} else if(p.getJumpCount() == 9){
			p.setPoint(new Point(p.getPoint().getX(), p.getPoint().getY() + 3));
			p.setJumpCount(p.getJumpCount() + 1);
		} else if(p.getJumpCount() == 10){
			p.setPoint(new Point(p.getPoint().getX(), p.getPoint().getY() + 6));
			p.setJumpCount(p.getJumpCount() + 1);
		} else if(p.getJumpCount() == 11){
			p.setPoint(new Point(p.getPoint().getX(), p.getPoint().getY() + 11));
			p.setJumpCount(p.getJumpCount() + 1);
		} else if(p.getJumpCount() == 12){
			p.setPoint(new Point(p.getPoint().getX(), p.getPoint().getY() + 18));
			p.setJumpCount(p.getJumpCount() + 1);

		} else if(p.getJumpCount() == 13){
			p.setPoint(new Point(p.getPoint().getX(), p.getPoint().getY() + 25));
			//p.setJumpCount(p.getJumpCount() + 1);
			p.setSprite(0);
			p.setJumping(false);
			p.setAniState(0);
		} 
	}
	
	public void jump(){
		if(p1.isJumping()) {
			if(p1.getJumpPixels() < p1.getJumpHeight() && p1.getiFactor() >= -p1.getiDefault()) {
				p1.setPoint(new Point(p1.getPoint().getX(), p1.getPoint().getY() - p1.getiFactor()));
				p1.setJumpPixels(p1.getJumpPixels() + 1);
				p1.setiFactor(p1.getiFactor() - 1);
			} if(p1.getiFactor() < -p1.getiDefault()) {
				p1.setJumping(false);
				p1.setiFactor(p1.getiDefault());
				p1.setJumpPixels(0);
			}
		}
		if(p2.isJumping()) {
			if(p2.getJumpPixels() < p2.getJumpHeight() && p2.getiFactor() >= -p2.getiDefault()) {
				p2.setPoint(new Point(p2.getPoint().getX(), p2.getPoint().getY() - p2.getiFactor()));
				p2.setJumpPixels(p2.getJumpPixels() + 1);
				p2.setiFactor(p2.getiFactor() - 1);
			} if(p2.getiFactor() < -p2.getiDefault()) {
				p2.setJumping(false);
				p2.setiFactor(p2.getiDefault());
				p2.setJumpPixels(0);
			}
		}
	}
	
	// Action methods under here.
	
	// KeyListener checks to see which key is pressed, then calls the generic move method
	
	@Override
	public void keyPressed(KeyEvent e) {
		
		// PLAYER 1 CONTROLS
		
			// Moving
		if((e.getKeyCode() == KeyEvent.VK_RIGHT && p1.isIdle()) || 
			(e.getKeyCode() == KeyEvent.VK_LEFT && p1.isIdle())){
			//moveP(p1, e.getKeyCode());
			if(!p1.isWalking())
				p1.setCountAni(p1.getAlert() + 1);
			p1.setSide(e.getKeyCode());
			p1.setWalking(true);
			p1.setAniState(1);
		}
			// Jumping
		if(e.getKeyCode() == KeyEvent.VK_UP && p1.isIdle() && (!p1.isJumping())){
			p1.setJumpCount(0);
			p1.setCountAni(p1.getWalk() + 1);
			p1.setJumping(true);
			p1.setAniState(2);
		}
			// Blocking
		if(e.getKeyCode() == KeyEvent.VK_DOWN && p1.isIdle()){
			p1.setAniState(3);
			p1.setBlocking(true);
			p1.setIdle(false);
		}
			// Attack Moves
		if(e.getKeyCode() == KeyEvent.VK_COMMA && p1.isIdle()) {
			p1.setCountAni(p1.getPunchNum() + 1);
			p1.setAniState(5);
			p1.setIdle(false);
		}
		if(e.getKeyCode() == KeyEvent.VK_PERIOD && p1.isIdle()) {
			p1.setCountAni(p1.getBlockHit() + 1);
			p1.setAniState(4);
			p1.setIdle(false);
		}
		if(e.getKeyCode() == KeyEvent.VK_SLASH && p1.isIdle()) {
			//p1.special(p2, 80);
		}
		
		// PLAYER 2 CONTROLS
		
			// Moving
		if((e.getKeyCode() == KeyEvent.VK_A && p2.isIdle())|| 
			(e.getKeyCode() == KeyEvent.VK_D && p2.isIdle())){
			//moveP(p2, e.getKeyCode());
			if(!p2.isWalking())
				p2.setCountAni(p1.getAlert() + 1);
			p2.setSide(e.getKeyCode());
			p2.setWalking(true);
			p2.setAniState(1);
		}
			// Jumping
		if(e.getKeyCode() == KeyEvent.VK_W && p2.isIdle() && (!p2.isJumping())){
			p2.setJumpCount(0);
			p2.setCountAni(p2.getWalk() + 1);
			p2.setJumping(true);
			p2.setAniState(2);
		}
			// Blocking
		if(e.getKeyCode() == KeyEvent.VK_S && p2.isIdle()){
			//System.out.println("Block!");
			p2.setAniState(3);
			p2.setBlocking(true);
			p2.setIdle(false);
		}
			// Attack Moves
		if(e.getKeyCode() == KeyEvent.VK_G && p2.isIdle()) {
			p2.setCountAni(p2.getPunchNum() + 1);
			p2.setAniState(5);
			p2.setIdle(false);
		}
		if(e.getKeyCode() == KeyEvent.VK_H && p2.isIdle()) {
			p2.setCountAni(p2.getBlockHit() + 1);
			p2.setAniState(4);
			p2.setIdle(false);
		}
		if(e.getKeyCode() == KeyEvent.VK_J && p2.isIdle()) {
			//p2.special(p1, 80);
		}
	}

	@Override
	public void keyReleased(KeyEvent e) {
		if(e.getKeyCode() == KeyEvent.VK_RIGHT || 
				e.getKeyCode() == KeyEvent.VK_LEFT){
			p1.setAniState(0);
			p1.setWalking(false);
		}
		
		if(e.getKeyCode() == KeyEvent.VK_A || 
				e.getKeyCode() == KeyEvent.VK_D){
			p2.setAniState(0);
			p2.setWalking(false);
		}
		
		if(e.getKeyCode() == KeyEvent.VK_DOWN && !p1.isIdle()){
			p1.setAniState(0);
			p1.setIdle(true);
			p1.setBlocking(false);
		}
		
		if(e.getKeyCode() == KeyEvent.VK_S && !p2.isIdle()){
			p2.setAniState(0);
			p2.setIdle(true);
			p2.setBlocking(false);
		}
	}

	@Override
	public void keyTyped(KeyEvent e) {
		// TODO Auto-generated method stub
		
	}

}
